package com.yue92.datalife.config;

import com.fasterxml.jackson.databind.ObjectMapper;
import com.yue92.datalife.common.Constant;
import com.yue92.datalife.exception.UncheckedException;
import com.yue92.datalife.filter.ClientAuthorizationFilter;
import com.yue92.datalife.response.ResponseResource;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Configuration;
import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.config.http.SessionCreationPolicy;
import org.springframework.security.core.AuthenticationException;
import org.springframework.security.web.AuthenticationEntryPoint;
import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;
import org.springframework.stereotype.Component;
import org.springframework.web.servlet.config.annotation.CorsRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;

@Configuration
public class WebMvcConfiguration implements WebMvcConfigurer {

    @Override
    public void addCorsMappings(CorsRegistry registry) {
        registry.addMapping("/api/**")
                .allowedOrigins("*")
                .allowCredentials(true)
                .allowedMethods("GET", "POST", "DELETE", "PUT")
                .maxAge(3600 * 24);
    }

    @Configuration
    public static class WebSecurityConfiguration extends WebSecurityConfigurerAdapter {

        @Autowired
        private ClientAuthorizationFilter clientAuthorizationFilter;

        @Autowired
        private CustomAuthenticationEntryPoint customAuthenticationEntryPoint;

        @Override
        protected void configure(HttpSecurity http) throws Exception {
//            http.authorizeRequests().anyRequest().permitAll();

            http.csrf().disable()
                    .cors()
                    .and().sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS)
                    .and().exceptionHandling().authenticationEntryPoint(customAuthenticationEntryPoint)
                    .and().addFilterBefore(clientAuthorizationFilter, UsernamePasswordAuthenticationFilter.class)
                    .authorizeRequests().antMatchers("/api/v1/users/login").permitAll()
                    .and().authorizeRequests().antMatchers("/api/v1/users/test").permitAll()
                    .antMatchers("/api/**").authenticated();
        }
    }

    @Component
    public static class CustomAuthenticationEntryPoint implements AuthenticationEntryPoint {

        @Autowired
        private ObjectMapper objectMapper;

        @Override
        public void commence(
                HttpServletRequest request, HttpServletResponse response, AuthenticationException authException)
                throws IOException, ServletException {

            UncheckedException exception = (UncheckedException) request.getAttribute(Constant.EXCEPTION_ATTRIBUTE);
            ResponseResource result = exception.getResult();
            response.setContentType(MediaType.APPLICATION_JSON_VALUE);
            response.setStatus(HttpStatus.OK.value());
            response.getWriter().write(objectMapper.writeValueAsString(result));
        }
    }
}
